#!/bin/bash

GRUPO=`pwd`
CONFDIR="config"
LIBDIR="lib"
BINDIR="bin"
INSTDIR="setup"
MAEDIR="mae"
ARRIDIR="arribos"
ACEPDIR="aceptados"
RECHDIR="rechazados"
PROCDIR="procesados"
REPODIR="reportes"
LOGDIR="log"
LOGEXT=".log"
LOGSIZE=400 #KB
DATASIZE=100 #MB
LOGFILE="$INSTDIR/InstalaV5.log"
CONFFILE="$CONFDIR/InstalaV5.conf"
SECUENCIA1="0"
SECUENCIA2="0"

function log() {
    logDate=`date "+%y-%m-%d_%H-%M-%S"` 
    echo "$logDate,$USER,$funcName,$1,$2" >> $LOGFILE
}

function echoAndLog() {
    echo -e "$2"
    log "$1" "$2"
}

function toLowerCase() {
    echo $1 | tr "[:upper:]" "[:lower:]"
}

function checkPrivileges() {
    if [ ! -w "$GRUPO" ]; then
        echo "No tiene permisos de escitura en el directorio de instalación"
        echo "Instalación cancelada"
        exit 2
    fi

    if [ ! -d "$INSTDIR" ]; then
        echo "No existe el directorio $INSTDIR"
        echo "Instalación cancelada"
        exit 2
    elif [ ! -w "$INSTDIR" ]; then
        echo "No tiene permisos de escritura sobre el directorio $INSTDIR"
        echo "Instalación cancelada"
        exit 2
    fi
}

function makeDir() {
    if [ ! -d $2 ]; then
        mkdir -p -m$1 $2 2>/dev/null 
    fi
}

function checkIfPerl() {
    funcName="checkIfPerl"
    perlVersion=`perl --version | grep -o "v[5-9]\.[0-9]\{1,\}\.[0-9]\{1,\}"`
    echoAndLog "I" "TP SO7508 Segundo Cuatrimestre 2012. Tema V Copyright © Grupo 5"
    if [ $? -ne 0 ]; then
        echoAndLog "SE" "Para instalar el TP es necesario contar con Perl 5 o superior instalado. Efectúe su instalación e inténtelo nuevamente. Proceso de Instalación Cancelado"
        exit 1
    else
        echoAndLog "I" "Perl Version: $perlVersion"
    fi
}

function showSetupStatus() {
    funcName="showSetupStatus"
    echoAndLog "I" "Directorio de Trabajo para la instalación: $GRUPO"
    echoAndLog "I" "Librería del Sistema: $CONFDIR"
    echoAndLog "I" "Estado de la instalación: PENDIENTE"
    echoAndLog "I" "Para completar la instalación Ud. Deberá:
        Definir el directorio de instalación de los ejecutables
        Definir el directorio de instalación de los archivos maestros
        Definir el directorio de arribo de archivos externos
        Definir el espacio mínimo libre para el arribo de archivos externos
        Definir el directorio de grabación de los archivos externos rechazados
        Definir el directorio de grabación de los logs de auditoria
        Definir la extensión y tamaño máximo para los archivos de log
        Definir el directorio de grabación de los reportes de salida"
}

function setRunnableFilesPath() {
    funcName="setRunnableFilesPath"
    isValid=0
    while [ "$isValid" -eq 0 ]; do
        echoAndLog "I" "Defina el directorio de instalación de los ejecutables($grupo/bin):"
        read path
        if [ ! -z "$path" ]; then
            value=`echo $path | grep "^\(\w\|_\)\+\(/\(\w\|_\)\+\)*$"`
            if [ $? -eq 0 ]; then
                BINDIR=$path
                isValid=1
            else
                echoAndLog "E" "El directorio ingresado es invalido."
            fi
        else
            isValid=1
        fi 
    done
}

function setMasterFilesPath() {
    funcName="setMasterFilesPath"
    isValid=0
    while [ "$isValid" -eq 0 ]; do
        echoAndLog "I" "Defina el directorio de instalación de los archivos maestros($grupo/mae):"
        read path
        if [ ! -z "$path" ]; then
            value=`echo $path | grep "^\(\w\|_\)\+\(/\(\w\|_\)\+\)*$"`
            if [ $? -eq 0 ]; then
                MAEDIR=$path
                isValid=1
            else
                echoAndLog "E" "El directorio ingresado es invalido."
            fi
        else
            isValid=1
        fi 
    done
}

function setExternalFilesPath() {
    funcName="setExternalFilesPath"
    isValid=0
    while [ "$isValid" -eq 0 ]; do
        echoAndLog "I" "Defina el directorio de arribo de archivos externos($grupo/arribos):"
        read externalPath
        if [ ! -z "$externalPath" ]; then
            value=`echo $externalPath | grep "^\(\w\|_\)\+\(/\(\w\|_\)\+\)*$"`
            if [ $? -eq 0 ]; then
                ARRIDIR=$externalPath
                isValid=1
            else
                echoAndLog "E" "El directorio ingresado es invalido."
            fi
        else
            isValid=1
        fi 
    done
    freeSize=0
    while [ $freeSize -lt $DATASIZE ]; do
        isValid=0
        while [ "$isValid" -eq 0 ]; do    
            echoAndLog "I" "Defina el espacio mínimo libre para el arribo de archivos externos en Mbytes (100):"
            read dataSize
            if [ ! -z $dataSize ]; then
                value=`echo $dataSize | grep "^[0-9]\+$"`
                if [ $? -eq 0 ]; then
                    DATASIZE=$dataSize
                    isValid=1
                else
                    echoAndLog "E" "El valor ingresado es invalido."
                fi
            else
                isValid=1
            fi
        done

        freeSize=`df $GRUPO | tail -n 1 | sed 's/\s\+/ /g' | cut -d ' ' -f 4`
        let freeSize=$freeSize/1024
        if [ $freeSize -lt $DATASIZE ]; then
            echoAndLog "E" "Insuficiente espacio en disco. Espacio disponible: $freeSize Mb. Espacio requerido $DATASIZE Mb.
            Cancele la instalación e inténtelo mas tarde o vuelva a intentarlo con otro valor."
        fi
    done
}

function setAcceptedFilesPath() {
    funcName="setAcceptedFilesPath"
    isValid=0
    while [ "$isValid" -eq 0 ]; do
        echoAndLog "I" "Defina el directorio de grabación de los archivos externos aceptados ($grupo/aceptados):"
        read path
        if [ ! -z "$path" ]; then
            value=`echo $path | grep "^\(\w\|_\)\+\(/\(\w\|_\)\+\)*$"`
            if [ $? -eq 0 ]; then
                ACEPDIR=$path
                isValid=1
            else
                echoAndLog "E" "El directorio ingresado es invalido."
            fi
        else
            isValid=1
        fi 
    done
}

function setRejectedFilesPath() {
    funcName="setRejectedFilesPath"
    isValid=0
    while [ "$isValid" -eq 0 ]; do
        echoAndLog "I" "Defina el directorio de grabación de los archivos externos rechazados ($grupo/rechazados):"
        read path
        if [ ! -z "$path" ]; then
            value=`echo $path | grep "^\(\w\|_\)\+\(/\(\w\|_\)\+\)*$"`
            if [ $? -eq 0 ]; then
                RECHDIR=$path
                isValid=1
            else
                echoAndLog "E" "El directorio ingresado es invalido."
            fi
        else
            isValid=1
        fi 
    done
}

function setProcessedFilesPath() {
    funcName="setProcessedFilesPath"
    isValid=0
    while [ "$isValid" -eq 0 ]; do
        echoAndLog "I" "Defina el directorio de grabación de los archivos procesados($grupo/procesados):"
        read path
        if [ ! -z "$path" ]; then
            value=`echo $path | grep "^\(\w\|_\)\+\(/\(\w\|_\)\+\)*$"`
            if [ $? -eq 0 ]; then
                PROCDIR=$path
                isValid=1
            else
                echoAndLog "E" "El directorio ingresado es invalido."
            fi
        else
            isValid=1
        fi 
    done
}

function showLogInformation() {
    funcName="showLogInformation"
    echoAndLog "I" "Los Logs de este sistema se grabaran en: $grupo/log. La extensión de los archivos de log es: .log"
}

function setLogDirSize() {
    funcName="setLogDirSize"
    isValid=0
    while [ "$isValid" -eq 0 ]; do
        echoAndLog "I" "Defina el tamaño máximo para los archivos $LOGEXT en Kbytes (400):"
    read logSize
    if [ ! -z $logSize ]; then
        value=`echo $logSize | grep "^[0-9]\+$"`
        if [ $? -eq 0 ]; then
            LOGSIZE=$logSize
            isValid=1
        else
            echoAndLog "E" "El valor ingresado es invalido."
        fi
    else
        isValid=1
    fi
    done
}

function setReportsFilesPath() {
    funcName="setReportsFilesPath"
    isValid=0
    while [ "$isValid" -eq 0 ]; do
        echoAndLog "I" "Defina el directorio de grabación de los reportes de salida($grupo/reportes):"
        read path
        if [ ! -z "$path" ]; then
            value=`echo $path | grep "^\(\w\|_\)\+\(/\(\w\|_\)\+\)*$"`
            if [ $? -eq 0 ]; then
                REPODIR=$path
                isValid=1
            else
                echoAndLog "E" "El directorio ingresado es invalido."
            fi
        else
            isValid=1
        fi 
    done
}

function showSetupConfig() {
    funcName="showSetupConfig"
    echoAndLog "I" "TP SO7508 1mer cuatrimestre 2012. Tema x Copyright © Grupo 5"
    echoAndLog "I" "Librería del Sistema: $CONFDIR"
    echoAndLog "I" "Ejecutables: $BINDIR"
    echoAndLog "I" "Archivos maestros: $MAEDIR"
    echoAndLog "I" "Directorio de arribo de archivos externos: $ARRIDIR"
    echoAndLog "I" "Espacio mínimo libre para arribos: $DATASIZE Mb"
    echoAndLog "I" "Archivos externos aceptados: $ACEPDIR"
    echoAndLog "I" "Archivos externos rechazados: $RECHDIR"
    echoAndLog "I" "Archivos procesados: $PROCDIR"
    echoAndLog "I" "Reportes de salida: $REPODIR"
    echoAndLog "I" "Logs de auditoria del Sistema: LOGDIR/<comando>.LOGEXT"
    echoAndLog "I" "Tamaño máximo para los archivos de log del sistema: $LOGSIZE Kb"
    echoAndLog "I" "Estado de la instalación: LISTA"
}

function confirmSetupConfig() {
    funcName="confirmSetupConfig"
    echoAndLog "I" "Los datos ingresados son correctos? (Si-No)"
    read confirmation
    if [ "$confirmation" = "" ] || [ `toLowerCase $confirmation` != "si" ]; then
        clear
        return 1
    else
        return 0
    fi
}

function makeDirs() {
    clear
    echo "Creando Estructuras de directorio..."
    makeDir 755 "$GRUPO/$BINDIR"
    makeDir 755 "$GRUPO/$MAEDIR"
    makeDir 755 "$GRUPO/$ARRIDIR"
    makeDir 755 "$GRUPO/$RECHDIR"
    makeDir 755 "$GRUPO/$ACEPDIR"
    makeDir 755 "$GRUPO/$PROCDIR"
    makeDir 755 "$GRUPO/$LOGDIR"
    makeDir 755 "$GRUPO/$REPODIR"
}

function confirmInstall() {
    funcName="confirmInstall"
    echoAndLog "I" "Iniciando Instalación. Está Ud. seguro? (Si-No):"
    read confirmation
    if [ "$confirmation" = "" ] || [ `toLowerCase $confirmation` != "si" ]; then
        echoAndLog "I" "Instalación cancelada"
        exit 1
    fi
}

function moveFile() {
    if [ -f "$2/${1##*/}" ]; then
        return 2
    fi
    if [ ! -f $1 ]; then 
        log "E" "200:Archivo inexistente: ${1##*/}" 
        return 1
    elif [ ! -d $2 ]; then
        log "E" "200:Directorio inexistente: $2"
        return 1
    else
        mv $1 $2 2>/dev/null
        if [ $? -ne 0 ]; then
            log "E" "210:No se pudo mover el archivo: ${1##*/}"
            return 1
        else
            chmod "$3" "$2/${1##*/}" 2>/dev/null
        fi
    fi
}

function moveMasterFiles() {
    echo "Instalando Archivos Maestros"
#Mover maestros    moveFile "$GRUPO/$INSTDIR/encuestas.mae" "$GRUPO/$MAEDIR" "444"
}

function moveLibFiles() {
   moveFile "$GRUPO/$INSTDIR/MoverV5.sh" "$GRUPO/$LIBDIR" "775"
   moveFile "$GRUPO/$INSTDIR/LoguearV5.sh" "$GRUPO/$LIBDIR" "775"
   moveFile "$GRUPO/$INSTDIR/StartD.sh" "$GRUPO/$LIBDIR" "775"
   moveFile "$GRUPO/$INSTDIR/StopD.sh" "$GRUPO/$LIBDIR" "775"
   moveFile "$GRUPO/$INSTDIR/MirarV5.sh" "$GRUPO/$LIBDIR" "775"
}

function moveRunnableFiles() {
    echo "Instalando Programas y Funciones"
    moveFile "$GRUPO/$INSTDIR/IniciarV5.sh" "$GRUPO/$BINDIR" "775"
    moveFile "$GRUPO/$INSTDIR/ListarV5.pl" "$GRUPO/$BINDIR" "775"
    moveFile "$GRUPO/$INSTDIR/BuscarV5.sh" "$GRUPO/$BINDIR" "775"
    moveFile "$GRUPO/$INSTDIR/DetectarV5.sh" "$GRUPO/$BINDIR" "775"
}

function config() {
    if [ -f $CONFFILE ]; then
        GRUPO=`grep "GRUPO" $CONFFILE | cut -s -f2 -d'='`
        CONFDIR=`grep "CONFDIR" $CONFFILE | cut -s -f2 -d'='`
        BINDIR=`grep "BINDIR" $CONFFILE | cut -s -f2 -d'='`
        MAEDIR=`grep "MAEDIR" $CONFFILE | cut -s -f2 -d'='`
        ARRIDIR=`grep "ARRIDIR" $CONFFILE | cut -s -f2 -d'='`
        ACEPDIR=`grep "ACEPDIR" $CONFFILE | cut -s -f2 -d'='`
        RECHDIR=`grep "RECHDIR" $CONFFILE | cut -s -f2 -d'='`
        PROCDIR=`grep "PROCDIR" $CONFFILE | cut -s -f2 -d'='`
        REPODIR=`grep "REPODIR" $CONFFILE | cut -s -f2 -d'='`
        LOGDIR=`grep "LOGDIR" $CONFFILE | cut -s -f2 -d'='`
        LOGEXT=`grep "LOGEXT" $CONFFILE | cut -s -f2 -d'='`
        LOGSIZE=`grep "LOGSIZE" $CONFFILE | cut -s -f2 -d'='`
        DATASIZE=`grep "DATASIZE" $CONFFILE | cut -s -f2 -d'='`
        SECUENCIA1=`grep "SECUENCIA1" $CONFFILE | cut -s -f2 -d'='`
        SECUENCIA2=`grep "SECUENCIA2" $CONFFILE | cut -s -f2 -d'='`
    fi
}

function saveConfig() {
    echo "Actualizando la configuración del sistema"
    logDate=`date "+%y-%m-%d_%H-%M-%S"`
    echo "GRUPO=$GRUPO=$USER=$logDate" > $CONFFILE
    echo "CONFDIR=$CONFDIR=$USER=$logDate" >> $CONFFILE
    echo "BINDIR=$BINDIR=$USER=$logDate" >> $CONFFILE
    echo "MAEDIR=$MAEDIR=$USER=$logDate" >> $CONFFILE
    echo "ARRIDIR=$ARRIDIR=$USER=$logDate" >> $CONFFILE
    echo "ACEPDIR=$ACEPDIR=$USER=$logDate" >> $CONFFILE
    echo "RECHDIR=$RECHDIR=$USER=$logDate" >> $CONFFILE
    echo "PROCDIR=$PROCDIR=$USER=$logDate" >> $CONFFILE
    echo "REPODIR=$REPODIR=$USER=$logDate" >> $CONFFILE
    echo "LOGDIR=$LOGDIR=$USER=$logDate" >> $CONFFILE
    echo "LOGEXT=$LOGEXT=$USER=$logDate" >> $CONFFILE
    echo "LOGSIZE=$LOGSIZE=$USER=$logDate" >> $CONFFILE
    echo "DATASIZE=$DATASIZE=$USER=$logDate" >> $CONFFILE
    echo "SECUENCIA1=$SECUENCIA1=$USER=$logDate" >> $CONFFILE
    echo "SECUENCIA2=$SECUENCIA2=$USER=$logDate" >> $CONFFILE
}

function checkSetupStatus {
    files=(
        "$GRUPO/$BINDIR/IniciarV5.sh"
        "$GRUPO/$BINDIR/DetectaV5.sh"
        "$GRUPO/$BINDIR/BuscarV5.sh"
        "$GRUPO/$BINDIR/ListarV5.pl"
        "$GRUPO/$LIBDIR/MoverV5.sh"
        "$GRUPO/$LIBDIR/LoguearV5.sh"
        "$GRUPO/$LIBDIR/StopD.sh"
        "$GRUPO/$LIBDIR/StartD.sh"
        "$GRUPO/$LIBDIR/MirarV5.sh"
    )
    masterFiles=(
        "$GRUPO/$MAEDIR/hola.txt"
    )
    installedFilesCount=0
    installedMasterFilesCount=0
    notInstalledFilesCount=0
    unset installedFiles
    unset installedMasterFiles
    unset notInstalledFiles
    for archivo in ${files[*]}
    do
        if [ -f "$archivo" ]; then
            owner=`ls -l $archivo | awk '{print $3 " " $6 " " $7}'`
            installedFiles[$installedFilesCount]="${archivo##*/}"
            let installedFilesCount=$installedFilesCount+1
        else
            notInstalledFiles[$notInstalledFilesCount]="${archivo##*/}"
            let notInstalledFilesCount=$notInstalledFilesCount+1
        fi
    done
   for archivo in ${masterFiles[*]}
    do
        if [ -f "$archivo" ]; then
            owner=`ls -l $archivo | awk '{print $3 " " $6 " " $7}'`
            installedMasterFiles[$installedMasterFilesCount]="${archivo##*/}"
            let installedMasterFilesCount=$installedMasterFilesCount+1
        else
            notInstalledFiles[$notInstalledFilesCount]="${archivo##*/}"
            let notInstalledFilesCount=$notInstalledFilesCount+1
        fi
    done
    if [ $installedFilesCount -gt 0 ] && [ -f "$CONFFILE" ]; then
        if [ $notInstalledFilesCount -gt 0 ]; then
            status=2 #Incompleta
        else
            status=0 #Completa
        fi                
    else
        status=1 #No instalado
    fi

    return $status
}

function confirmCompleteInstall() {
    funcName="confirmCompleteInstall"
    echoAndLog "I" "Desea completar la instalacion? (Si-No):"
    read confirmation
    if [ "$confirmation" = "" ] || [ `toLowerCase $confirmation` != "si" ]; then
        echoAndLog "I" "Instalación cancelada"
        exit 1
    fi
}

function showIncompletedSetupStatus() {
    funcName="showIncompletedSetupStatus"
    checkSetupStatus
    echoAndLog "I" "TP SO7508 Segundo Cuatrimestre 2012. Tema V Copyright © Grupo 5"
    if [ $installedFilesCount -gt 0 ] || [ $installedMasterFilesCount -gt 0 ]; then
	echoAndLog "I" "Componentes Existentes:"
    fi
    if [ $installedFilesCount -gt 0 ]; then
	echo -e -n "\t"
	echoAndLog "I" "Ejecutables: $BINDIR"
        arr=("${installedFiles[@]}")
        for index in ${!arr[*]}
        do
            echo -e -n "\t\t"
            echoAndLog "I" "${arr[$index]}"
        done
    fi
    if [ $installedMasterFilesCount -gt 0 ]; then
        echo -e -n "\t"
        echoAndLog "I" "Archivos maestros: $MAEDIR"
        arr=("${installedMasterFiles[@]}")
        for index in ${!arr[*]}
        do
            echo -e -n "\t\t"
            echoAndLog "I" "${arr[$index]}"
        done
    fi
    if [ $notInstalledFilesCount -gt 0 ]; then 
        echoAndLog "I" "Componentes faltantes:"
        for item in ${notInstalledFiles[*]}
        do
            echo -e -n "\t"
            echoAndLog "I" "$item"
        done
    fi
    echoAndLog "I" "Estado de la instalación: INCOMPLETA"
    confirmCompleteInstall
}	

function showCompletedSetupStatus() {
    funcName="showCompletedSetupStatus"
    checkSetupStatus
    echoAndLog "I" "TP SO7508 Segundo Cuatrimestre 2012. Tema V Copyright © Grupo 5"
    echoAndLog "I" "Librería del Sistema: $CONFDIR"
    echoAndLog "I" "Ejecutables: $BINDIR"
    echoAndLog "I" "Archivos maestros: $MAEDIR"
    echoAndLog "I" "Directorio de arribo de archivos externos: $ARRIDIR"
    echoAndLog "I" "Archivos externos aceptados: $ACEPDIR"
    echoAndLog "I" "Archivos externos rechazados: $RECHDIR"
    echoAndLog "I" "Archivos procesados: $PROCDIR"
    echoAndLog "I" "Reportes de salida: $REPODIR"
    echoAndLog "I" "Logs de auditoria del Sistema: LOGDIR/<comando>.LOGEXT"
    echoAndLog "I" "Estado de la instalación: COMPLETA"
    echoAndLog "I" "Proceso de Instalación Cancelado"
}

#MAIN
clear
funcName="main"
log "I" "Comando InstalaV5 Inicio de Ejecución"
checkPrivileges
config
checkSetupStatus
case "$?" in
    0) #instalación completa
	showCompletedSetupStatus
        exit 0;;
    1) #No hay instalación previa        
        checkIfPerl
        showSetupStatus
        changeConfig=1
        setRunnableFilesPath
        setMasterFilesPath
        while [ $changeConfig -ne 0 ]; do
            setExternalFilesPath
            setAcceptedFilesPath
            setRejectedFilesPath
            setProcessedFilesPath
            showLogInformation
            setLogDirSize
	    clear
            showSetupConfig
            confirmSetupConfig
            changeConfig=$?
        done;;
    2) #instalación previa incompleta
        showIncompletedSetupStatus
	showSetupConfig
	;;
esac
confirmInstall
makeDirs
moveMasterFiles
moveRunnableFiles
moveLibFiles
saveConfig
funcName="main"
echoAndLog "I" "Instalación concluida"
exit $?
